from utils.word.core_word import WordAnalyzer
from utils.sentiment.core_senti import SentimentAnalyzer
from utils.common.db import DBConnector
from utils.common.logger import log
from utils.classification.core_category import CategoryMapper
from utils.classification.core_fasttext import FastTextClassifier


class CoreCaller:
    def __init__(self, db_config: dict = None):
        self.word_analyzer = None
        self.sentiment_analyzer = None
        self.category_mapper = None
        self.db_config = db_config

    def tag_DBNews(self):
        '''
        定时调用接口，为数据库中新加入的新闻打标签
        '''

        db = DBConnector(self.db_config)
        if db.connect() == False:
            log.logger.warning("Cannot connect to database!")
            return None

        if self.word_analyzer is None:
            self.word_analyzer = WordAnalyzer()

        dbData = db.query(
            "select news_id, content from main where keywords is null and content is not null")
        dbData = self.word_analyzer.tag_news(dbData)

        for row in dbData:
            db.update("update main set keywords = '{}' where news_id = {}".format(
                row["keywords"], row["news_id"]))

    def senti_DBNews(self):
        '''
        定时调用接口，为数据库中新加入的新闻打标签
        '''
        db = DBConnector(self.db_config)
        if db.connect() == False:
            log.logger.warning("Cannot connect to database!")
            return None

        if self.sentiment_analyzer is None:
            self.sentiment_analyzer = SentimentAnalyzer()

        dbData = db.query(
            "select news_id, title, content from main where sentiment is null and content is not null")

        for idx, obj in enumerate(dbData):
            update_query = "update main "

            if((idx+1) % 1000 == 0):
                log.logger.info("{} news has been sentied".format(idx+1))

            score = self.sentiment_analyzer.senti_news(
                obj["title"], obj["content"])

            if score == 1:
                update_query += "set sentiment='正向' "
            elif score == -1:
                update_query += "set sentiment='负向' "
            else:
                update_query += "set sentiment='中立' "

            update_query += "where news_id={}".format(obj["news_id"])
            db.update(update_query)

    def update_Hotwords(self):
        '''
        定时调用接口，为不同种类新闻更新热词
        '''

        db = DBConnector(self.db_config)
        if db.connect() == False:
            log.logger.warning("Cannot connect to database!")
            return None

        if self.word_analyzer is None:
            self.word_analyzer = WordAnalyzer()

        keywords = db.query(
            "select keywords from main where keywords is not null and content is not null")
        hotwords = self.word_analyzer.get_hotwords(keywords)
        for idx, value in enumerate(hotwords):
            db.update("update hotwords set hotwords='{}',score={} where id={}".format(
                value[0], value[1], idx+1))

    def update_DBCategory(self):
        """
        定时调用接口，为数据库中新加入的新闻分类统一
        """
        db = DBConnector(self.db_config)
        if db.connect() == False:
            log.logger.warning("Cannot connect to database!")
            return None

        if self.category_mapper is None:
            self.category_mapper = CategoryMapper()

        dbData = db.query(
            "select news_id, category from main where keywords is null")
        dbData = self.category_mapper.unify_category(dbData)
        for row in dbData:
            db.update("update main set category='{}' where news_id={}".format(
                row["category"], row["news_id"]))

    def update_DBCluster(self):
        '''
        定时调用接口，为数据库的新闻专题做更新
        '''
        db = DBConnector(self.db_config)
        if db.connect() == False:
            log.logger.warning("Cannot connect to database!")
            return None

        classData = db.query(
            "select s_topic_id,specialtopic,information from topic")

        for classObject in classData:
            if classObject["information"] is None:
                continue
            
            more_info = classObject["information"].split(" ")
            news_list = self.search_tag(
                classObject["specialtopic"], more_info)

            db.update(
                f"delete from main_topic where s_topic_id = {classObject['s_topic_id']}")
            for news_id, relevant in news_list:
                db.update(
                    f"insert into main_topic(news_id,s_topic_id) values ({news_id},{classObject['s_topic_id']})")

    def search_tag(self, tag: str, more_info: list = [], N: int = 100):
        """
        根据用户输入的标签/专题，寻找最为相关的前N条
        """

        db = DBConnector(self.db_config)
        if db.connect() == False:
            log.logger.warning("Cannot connect to database!")
            return None

        if self.word_analyzer is None:
            self.word_analyzer = WordAnalyzer()

        # 将专题分词，进行细粒度匹配
        pair_list = self.word_analyzer.seg(tag)

        dbData = db.query(
            "select news_id,title,keywords from main where content is not null and keywords is not null")

        news_dict = {}
        for news in dbData:
            id = news["news_id"]
            news_dict[id] = 0  # 先把每个新闻对应的相关度设为0

            # 先对分词进行匹配，其权值最低
            for word in pair_list:
                news_dict[id] += (news["title"] +
                                  news["keywords"]).count(word)*0.2

            # 再对more_info进行匹配，权值较高
            for detail in more_info:
                news_dict[id] += (news["title"] +
                                  news["keywords"]).count(detail)*0.4

            # 若关键词直接出现，则优先匹配
            news_dict[id] += (news["title"] +
                              news["keywords"]).count(tag)*0.4

            if news_dict[id] == 0:
                news_dict.pop(id)

        return sorted(news_dict.items(), key=lambda x: x[1], reverse=True)[:N]
